package ss.pku.jsa.type.inference;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IOpenable;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaCore;

public class Main implements IApplication {
	public Object run(Object argsObj) throws Exception {

		String proj = System.getProperty("proj");
		if (proj != null) {
			analyzeProject(proj);
			BufferedReader in = new BufferedReader(new InputStreamReader(
					System.in));

			JqualPlugin.out.print("Project to analyze: ");
			String prev = proj;
			String line;
			while (!(line = in.readLine()).equals("quit")) {
				if (line.equals(""))
					line = prev;
				analyzeProject(proj);
				JqualPlugin.out.print("Files to analyze: ");
				prev = line;
			}
		} else {
			String path = System.getProperty("path");
			if (path == null) {
				path = "";
			} else if (path.charAt(path.length() - 1) != File.separatorChar) {
				path = path + File.separator;
			}

			String outfile = System.getProperty("output");
			PrintStream out = null;
			if (outfile != null) {
				try {
					out = new PrintStream(new FileOutputStream(outfile, false));
				} catch (FileNotFoundException e) {
					throw new IllegalArgumentException(
							"Could not open output file: " + outfile + "\n" + e);
				}
			}

			String filesArg = System.getProperty("file");

			IOpenable[] input = (IOpenable[]) null;
			if (filesArg != null) {
				if (filesArg.equals("all")) {
					input = new IOpenable[1];
					input[0] = ((IOpenable) JavaCore.create(getFolder(path)));
				} else {
					String[] files = filesArg.split(" ");
					for (int i = 0; i < files.length; i++) {
						files[i] = (path + files[i]);
					}
					input = getIOpenables(files);
				}
			}

			JqualPlugin.out.println("before");

			analyze(input, out);

			JqualPlugin.out.println("after");

			BufferedReader in = new BufferedReader(new InputStreamReader(
					System.in));

			JqualPlugin.out.print("Files to analyze: ");
			String line;
			while (!(line = in.readLine()).equals("quit")) {
				if (line.equals("")) {
					analyze(input, out);
				} else if (line.equals("l")) {
					JqualPlugin.limitFields = !JqualPlugin.limitFields;
					JqualPlugin.out.println("Limit "
							+ (JqualPlugin.limitFields ? "on" : "off"));
				} else if (line.equals("m")) {
					JqualPlugin.allowMerge = !JqualPlugin.allowMerge;
					JqualPlugin.out.println("Allow Merge "
							+ (JqualPlugin.limitFields ? "on" : "off"));
				} else {
					String[] files = line.split(" ");
					for (int i = 0; i < files.length; i++) {
						files[i] = (path + files[i]);
					}
					input = getIOpenables(files);
					analyze(input, out);
				}

				JqualPlugin.out.print("Files to analyze: ");
			}
		}

		return null;
	}

	public static IOpenable[] getIOpenables(String[] names) {
		IOpenable[] inputs = new IOpenable[names.length];
		for (int i = 0; i < names.length; i++) {
			IFile file = getFile(names[i]);
			if (file == null) {
				System.err.println("Could not open file: " + names[i]);
				return null;
			}
			IOpenable input = (IOpenable) JavaCore.create(file);
			inputs[i] = input;
		}
		return inputs;
	}

	public static Analysis analyze(IOpenable[] inputs, PrintStream out) {
		Analysis results = null;
		results = JqualPlugin.analyze(inputs, true);
		if (out != null)
			out.println(results);
		else {
			JqualPlugin.out.println(results);
		}
		return results;
	}

	public static void analyzeProject(String name) {
		IJavaProject proj = JqualPlugin.getJavaProject(name);
		if (proj == null) {
			System.err.println("Could not open project: " + name);
			return;
		}
		try {
			Analysis results = JqualPlugin.analyze(proj);
			JqualPlugin.out.println(results);
		} catch (Exception e) {
			JqualPlugin.out.println("Failed to analyze: \n" + proj + "\n" + e);
			e.printStackTrace();
		}
	}

	public static IFile getFile(String name) {
		IPath path = new Path(name);
		IWorkspaceRoot myWorkspaceRoot = JqualPlugin.getWorkspace().getRoot();
		IFile target = myWorkspaceRoot.getFileForLocation(path);
		return target;
	}

	public static IPackageFragment getPackage(String name) {
		IFolder f = getFolder(name);
		return (IPackageFragment) JavaCore.create(f);
	}

	public static IFolder getFolder(String name) {
		IPath path = new Path(name);
		IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace()
				.getRoot();
		IFolder target = (IFolder) myWorkspaceRoot
				.getContainerForLocation(path);
		return target;
	}

	@Override
	public Object start(IApplicationContext arg0) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub
		
	}
}
